﻿using System.Linq.Expressions;

namespace KinonekoSoftware.CodariaDB.Runtimes.Abstractions
{
    public interface ILazyCollection<T> : ILiteCollection<T>
    {

    }

    internal class LazyCollection<T> : ILazyCollection<T> where T : class
    {
        private readonly Lazy<ILiteCollection<T>> _factory;

        //
        //
        private ILiteCollection<T> _lazy => _factory.Value;


        public LazyCollection(Repository repository, string collectionName)
        {
            _factory        = new Lazy<ILiteCollection<T>>(() => repository.GetCollection<T>(collectionName));
        }
        
        public ILiteCollection<T> Include<K>(Expression<Func<T, K>> keySelector)
        {
            return _lazy.Include(keySelector);
        }
        
        public ILiteCollection<T> Include(BsonExpression keySelector)
        {
            return _lazy.Include(keySelector);
        }
        
        public bool Upsert(T entity)
        {
            return _lazy.Upsert(entity);
        }
        
        public int Upsert(IEnumerable<T> entities)
        {
            return _lazy.Upsert(entities);
        }
        public bool Upsert(BsonValue id, T entity)
        {
            return _lazy.Upsert(id, entity);
        }
        public bool Update(T entity)
        {
            return _lazy.Update(entity);
        }
        public bool Update(BsonValue id, T entity)
        {
            return _lazy.Update(id, entity);
        }
        public int Update(IEnumerable<T> entities)
        {
            return _lazy.Update(entities);
        }
        public int UpdateMany(BsonExpression transform, BsonExpression predicate)
        {
            return _lazy.UpdateMany(transform, predicate);
        }
        public int UpdateMany(Expression<Func<T, T>> extend, Expression<Func<T, bool>> predicate)
        {
            return _lazy.UpdateMany(extend, predicate);
        }
        public BsonValue Insert(T entity)
        {
            return _lazy.Insert(entity);
        }
        public void Insert(BsonValue id, T entity)
        {
            _lazy.Insert(id, entity);
        }
        public int Insert(IEnumerable<T> entities)
        {
            return _lazy.Insert(entities);
        }
        public int InsertBulk(IEnumerable<T> entities, int batchSize = 5000)
        {
            return _lazy.InsertBulk(entities, batchSize);
        }
        public bool EnsureIndex(string name, BsonExpression expression, bool unique = false)
        {
            return _lazy.EnsureIndex(name, expression, unique);
        }
        public bool EnsureIndex(BsonExpression expression, bool unique = false)
        {
            return _lazy.EnsureIndex(expression, unique);
        }
        public bool EnsureIndex<K>(Expression<Func<T, K>> keySelector, bool unique = false)
        {
            return _lazy.EnsureIndex(keySelector, unique);
        }
        public bool EnsureIndex<K>(string name, Expression<Func<T, K>> keySelector, bool unique = false)
        {
            return _lazy.EnsureIndex(name, keySelector, unique);
        }
        public bool DropIndex(string name)
        {
            return _lazy.DropIndex(name);
        }
        public ILiteQueryable<T> Query()
        {
            return _lazy.Query();
        }
        public IEnumerable<T> Find(BsonExpression predicate, int skip = 0, int limit = 2147483647)
        {
            return _lazy.Find(predicate, skip, limit);
        }
        public IEnumerable<T> Find(Query query, int skip = 0, int limit = 2147483647)
        {
            return _lazy.Find(query, skip, limit);
        }
        public IEnumerable<T> Find(Expression<Func<T, bool>> predicate, int skip = 0, int limit = 2147483647)
        {
            return _lazy.Find(predicate, skip, limit);
        }
        public T FindById(BsonValue id)
        {
            return _lazy.FindById(id);
        }
        public T FindOne(BsonExpression predicate)
        {
            return _lazy.FindOne(predicate);
        }
        public T FindOne(string predicate, BsonDocument parameters)
        {
            return _lazy.FindOne(predicate, parameters);
        }
        public T FindOne(BsonExpression predicate, params BsonValue[] args)
        {
            return _lazy.FindOne(predicate, args);
        }
        public T FindOne(Expression<Func<T, bool>> predicate)
        {
            return _lazy.FindOne(predicate);
        }
        public T FindOne(Query query)
        {
            return _lazy.FindOne(query);
        }
        public IEnumerable<T> FindAll()
        {
            return _lazy.FindAll();
        }
        public bool Delete(BsonValue id)
        {
            return _lazy.Delete(id);
        }
        public int DeleteAll()
        {
            return _lazy.DeleteAll();
        }
        public int DeleteMany(BsonExpression predicate)
        {
            return _lazy.DeleteMany(predicate);
        }
        public int DeleteMany(string predicate, BsonDocument parameters)
        {
            return _lazy.DeleteMany(predicate, parameters);
        }
        public int DeleteMany(string predicate, params BsonValue[] args)
        {
            return _lazy.DeleteMany(predicate, args);
        }
        public int DeleteMany(Expression<Func<T, bool>> predicate)
        {
            return _lazy.DeleteMany(predicate);
        }
        public int Count()
        {
            return _lazy.Count();
        }
        public int Count(BsonExpression predicate)
        {
            return _lazy.Count(predicate);
        }
        public int Count(string predicate, BsonDocument parameters)
        {
            return _lazy.Count(predicate, parameters);
        }
        public int Count(string predicate, params BsonValue[] args)
        {
            return _lazy.Count(predicate, args);
        }
        public int Count(Expression<Func<T, bool>> predicate)
        {
            return _lazy.Count(predicate);
        }
        public int Count(Query query)
        {
            return _lazy.Count(query);
        }
        public long LongCount()
        {
            return _lazy.LongCount();
        }
        public long LongCount(BsonExpression predicate)
        {
            return _lazy.LongCount(predicate);
        }
        public long LongCount(string predicate, BsonDocument parameters)
        {
            return _lazy.LongCount(predicate, parameters);
        }
        public long LongCount(string predicate, params BsonValue[] args)
        {
            return _lazy.LongCount(predicate, args);
        }
        public long LongCount(Expression<Func<T, bool>> predicate)
        {
            return _lazy.LongCount(predicate);
        }
        public long LongCount(Query query)
        {
            return _lazy.LongCount(query);
        }
        public bool Exists(BsonExpression predicate)
        {
            return _lazy.Exists(predicate);
        }
        public bool Exists(string predicate, BsonDocument parameters)
        {
            return _lazy.Exists(predicate, parameters);
        }
        public bool Exists(string predicate, params BsonValue[] args)
        {
            return _lazy.Exists(predicate, args);
        }
        public bool Exists(Expression<Func<T, bool>> predicate)
        {
            return _lazy.Exists(predicate);
        }
        public bool Exists(Query query)
        {
            return _lazy.Exists(query);
        }
        public BsonValue Min(BsonExpression keySelector)
        {
            return _lazy.Min(keySelector);
        }
        public BsonValue Min()
        {
            return _lazy.Min();
        }
        public K Min<K>(Expression<Func<T, K>> keySelector)
        {
            return _lazy.Min(keySelector);
        }
        public BsonValue Max(BsonExpression keySelector)
        {
            return _lazy.Max(keySelector);
        }
        public BsonValue Max()
        {
            return _lazy.Max();
        }
        public K Max<K>(Expression<Func<T, K>> keySelector)
        {
            return _lazy.Max(keySelector);
        }
        public string Name
        {
            get => _lazy.Name;
        }
        public BsonAutoId AutoId
        {
            get => _lazy.AutoId;
        }
        public EntityMapper EntityMapper
        {
            get => _lazy.EntityMapper;
        }
    }
}